using System;
using System.Collections.Generic;
using System.Text;

using System.Data;
using System.Data.SqlClient;
using System.Configuration;

namespace Bots.Index
{
    public abstract class Finder
    {
        /// <summary>
        /// Database Table Name Map to Entity Object
        /// </summary>
        protected abstract string Table { get;}
        /// <summary>
        /// Entity Object Full Name
        /// </summary>
        protected abstract Type DomainObjectType { get;}

        private log4net.ILog logger = log4net.LogManager.GetLogger(typeof(Finder));

        public string Statement {
            get { return "select top 100 * from " + Table + " "; }
        }

        public List<DomainObject> FindAll(Type domainObjectType) {
            return Find(Statement);
        }

        public DomainObject FindByID(long domainObjectID) {
            List<DomainObject> list = FindByWhere(string.Format("ID={0}", domainObjectID));
            if (list.Count == 0) return Activator.CreateInstance(DomainObjectType, domainObjectID) as DomainObject;
            return list[0];
        }

        public List<DomainObject> FindByWhere(string clause)
        {
            return Find(Statement + "Where " + clause);
        }

        protected List<DomainObject> Find(string statement) {
            logger.Info("statement:" + statement);
            Console.WriteLine("statement:" + statement);
            List<DomainObject> list = new List<DomainObject>();
            SqlConnection connection = null;
            try
            {
                string connectionString = ConfigurationManager.ConnectionStrings["connectionString"].ConnectionString;
                connection = new SqlConnection(connectionString);
                connection.Open();
                SqlCommand cmd = new SqlCommand(statement, connection);
                cmd.CommandType = CommandType.Text;                              
                SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
                while (reader.Read())
                {
                    DomainObject obj = LoadFromReader(reader);
                    list.Add(obj);
                }
                reader.Close();
            }
            catch (Exception e1)
            {
                logger.Fatal(e1);
                throw e1;
            }
            finally
            {
                if (connection != null)
                {
                    connection.Close();
                }
            }
            return list;
        }

        public List<DomainObject> FindByIds(string ids)
        {
            string statement = string.Format("SELECT * FROM {0} Where ID IN({1})", Table,ids);
            return Find(statement);
        }

        /// <summary>
        /// Read single row
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="domainObjectType">Entity Type</param>
        /// <returns></returns>
        protected abstract DomainObject LoadFromReader(SqlDataReader reader);

        private string ToFormatString(long[] ids) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < ids.Length; i++) {
                sb.Append(i.ToString() + ",");
            }
            return sb.ToString().Substring(0, sb.Length - 1);
        }

    }
}
